//
//  HACLineNode.m
//  HStockCharts
//
//  Created by Hotacool on 2018/9/18.
//

#import "HACLineNode.h"
#import "HACLineChartDataSet.h"
#import "HACGradientWave.h"

@interface HACLineNode ()
/** 画线点数据 */
@property (nonatomic, strong) NSMutableArray *lineDrawingData;
/** 画笔 */
@property (nonatomic, strong) HACGradientWave *lineBrush;
@end

@implementation HACLineNode {
    NSInteger _maxPointCount;
}

- (void)removeNode {
    [super removeNode];
    [self.lineBrush removeBrush];
}

- (void)setUp {
    [super setUp];
    self.pointRect = CGRectZero;
    self.singleWidth = 1.0;
    _lineBrush = [[HACGradientWave alloc] initWithDataProvider:self];
}

- (void)setData:(HACChartData *)data {
    if (!data) {
        return;
    }
    _lineDicData = [NSMutableDictionary dictionary];
    _lineDrawingData = [NSMutableArray array];
    int index = 0, maxCount = 0;
    for (HACLineChartDataSet *dataSet in data.dataSets) {
        if ([dataSet isKindOfClass:[HACLineChartDataSet class]]) {
            HACLineComponents *lineItem = [[HACLineComponents alloc] init];
            lineItem.isCurve = dataSet.cubicEnabled;
            lineItem.lineColor = dataSet.lineColor;
            lineItem.fillColor = dataSet.fillColor;
            lineItem.isGradient = dataSet.gradientEnabled;
            lineItem.dashLengths = dataSet.lineDashPattern?:nil;
            lineItem.index = index;
            lineItem.lineBolder = dataSet.lineWidth>1?dataSet.lineWidth:1;
            [_lineDrawingData addObject:lineItem];
            NSArray *points = dataSet.values;
            if (points) {
                [_lineDicData setObject:points forKey:@(index)];
            }
            int tmpMax = (int)(points?points.count:0);
            if (tmpMax > maxCount) {
                maxCount = tmpMax;
            }
            index++;
        }
    }
    _maxPointCount = maxCount;
    self.startIndex = MAX(0, self.actualCount - self.visualCount);
    self.endIndex = MAX(self.visualCount, self.actualCount - 1);
    
    [super setData:data];
}

- (CGFloat)maxContentWidth {
    CGFloat max = 0;
    if (self.isCenter) {
        max = self.actualCount * self.singleWidth;
    } else {
        max = (self.actualCount - 1) * self.singleWidth;
    }
    return MAX(max , [super maxContentWidth]);
}

- (void)updateFrame {
    [super updateFrame];
    if (self.isCenter) {
        self.singleWidth = FormatValueWithRemain(self.relativeFrame.size.width / (self.visualCount), 3);// 可见数即visualCount
    }
}

- (void)setNeedsDisplay {
    [super setNeedsDisplay];
    if (self.hostLayer) {
        [self.lineBrush drawInLayer:self.hostLayer inRect:self.relativeFrame];
    }
}

- (NSInteger)actualCount {
    return _maxPointCount;
}

#pragma mark - provider protocol
- (NSArray *)lineDatasInRect:(CGRect)rect {
    if (!self.data)
        return nil;
    
    int index = 0;
    for (HACLineComponents *lineItem in self.lineDrawingData) {
        NSArray *points = _lineDicData[@(index)];
        if (!points) {
            continue;
        }
        lineItem.pointCount = (self.endIndex - self.startIndex) + 1;
        NSMutableArray *pointsArray = [NSMutableArray array];
        
        for (NSInteger i = self.startIndex; i <= self.endIndex && i < self.actualCount; i++) {
            if (i >= points.count) {
                break;
            }
            id pointData = points[i];
            CGFloat x = 0.0, y = 0.0;
            NSInteger idx = [self relativeIdxFromIndex:i];
            x = [self xPointForIndex:idx inRect:self.pointRect];
            if (self.isCenter) {//偏移1/2singleWidth,点居中
                x += self.singleWidth / 2;
            }
            CGFloat value = [self lineValueForItem:pointData lineIndex:lineItem.index];
            y = [self calculatorYForValue:value min:self.minValue max:self.maxValue inRect:self.pointRect];
            [pointsArray addObject:NSStringFromCGPoint(CGPointMake(x, y))];
        }
        lineItem.pointArray = pointsArray;
        index++;
    }
    return self.lineDrawingData;
}

- (CGFloat)lineValueForItem:(HACPointEntry *)data lineIndex:(NSInteger)index {
    return data.y;
}

// 计算最大，最小值
- (void)calculateLimitValue {
    CGFloat __block max = FLT_MIN;
    CGFloat __block min = FLT_MAX;
    [_lineDicData enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) {
        long start = self.startIndex;
        long len = self.endIndex - self.startIndex + 1;
        if (start+len>self.actualCount) {
            len = self.actualCount - start;
        }
        obj = [obj subarrayWithRange:NSMakeRange(start, len)];
        for (id p in obj) {
            CGFloat value = [self lineValueForItem:p lineIndex:0];
            if (value > max) {
                max = value;
            }
            if (value < min) {
                min = value;
            }
        }
    }];
    self.maxValue = (max == FLT_MIN) ? .0 : max;
    self.minValue = (min == FLT_MAX) ? .0 : min;
}

#pragma mark -- api
- (NSInteger)indexAtChartForCoordinate:(CGPoint)point {
    NSInteger focusIndex = [super indexAtChartForCoordinate:point];
    
    CGFloat offsetX = point.x - CGRectGetMinX(self.pointRect);
    focusIndex = offsetX / self.singleWidth;
    HACLineComponents *lineItem = self.lineDrawingData.firstObject;
    if (focusIndex > 0) {
        if (focusIndex >= lineItem.pointArray.count) {
            focusIndex = lineItem.pointArray.count - 1;
        }
    } else {
        focusIndex = 0;
    }
    return focusIndex;
}

- (CGPoint)pointAtChartForIndex:(NSInteger)index {
    CGPoint point = [super pointAtChartForIndex:index];
    HACLineComponents *lineItem = self.lineDrawingData.firstObject;
    if (lineItem.pointArray && lineItem.pointArray.count > 0) {
        if (index > 0) {
            if (lineItem.pointArray.count > index) {
                point = CGPointFromString(lineItem.pointArray[index]);
            } else {
                point = CGPointFromString(lineItem.pointArray.lastObject);
            }
        }
    }
    return point;
}

- (HACChartDataEntry*)dataAtChartForCoordinate:(CGPoint)point {
    HACChartDataEntry *indexData = [super dataAtChartForCoordinate:point];
    NSUInteger focusIndex = [self indexAtChartForCoordinate:point];
    NSArray *timelineData = [self.lineDicData objectForKey:@0];
    if (self.lineDicData && focusIndex < timelineData.count) {
        indexData = timelineData[focusIndex];
    }
    return indexData;
}

- (HACChartDataEntry*)dataAtChartForIndex:(NSUInteger)focusIndex {
    HACChartDataEntry *indexData = [super dataAtChartForIndex:focusIndex];
    NSArray *timelineData = [self.lineDicData objectForKey:@0];
    if (timelineData && focusIndex < timelineData.count) {
        indexData = timelineData[focusIndex];
    }
    return indexData;
}
@end
